Oracle: UPSERT(업데이트 또는 테이블에 삽입) 방법

您所在的位置:网站首页 oracle sql minus Oracle: UPSERT(업데이트 또는 테이블에 삽입) 방법

Oracle: UPSERT(업데이트 또는 테이블에 삽입) 방법

2023-03-07 10:44| 来源: 网络整理| 查看: 265

Oracle: UPSERT(업데이트 또는 테이블에 삽입) 방법

UPSERT 작업은 테이블에 데이터와 일치하는 행이 이미 있는지 여부에 따라 테이블에 행을 업데이트하거나 삽입합니다.

if table t has a row exists that has key X: update t set mystuff... where mykey=X else insert into t mystuff...

Oracle에는 특정 UPSERT 문구가 없기 때문에 이를 위한 가장 좋은 방법은 무엇입니까?

MERGE 문은 두 테이블 간의 데이터를 병합합니다.DUAL을 사용하면 이 명령을 사용할 수 있습니다.이는 동시 액세스로부터 보호되지 않습니다.

create or replace procedure ups(xa number) as begin merge into mergetest m using dual on (a = xa) when not matched then insert (a,b) values (xa,1) when matched then update set b = b+1; end ups; / drop table mergetest; create table mergetest(a number, b number); call ups(10); call ups(10); call ups(20); select * from mergetest; A B ---------------------- ---------------------- 10 2 20 1

위의 PL/SQL에 있는 듀얼 예시는 매우 좋았습니다.왜냐하면 저는 비슷한 일을 하고 싶었지만 클라이언트 측에서 하고 싶었기 때문입니다.여기 C#에서 직접 유사한 스테이트먼트를 전송하기 위해 사용한SQL이 있습니다.

MERGE INTO Employee USING dual ON ( "id"=2097153 ) WHEN MATCHED THEN UPDATE SET "last"="smith" , "name"="john" WHEN NOT MATCHED THEN INSERT ("id","last","name") VALUES ( 2097153,"smith", "john" )

단, C#의 관점에서 보면 업데이트 실행 및 영향을 받는 행이 0인지 확인하고 해당 행이 0인지 삽입되었는지 여부를 확인하는 것보다 속도가 느려집니다.

MERGE의 대안('구식 방식'):

begin insert into t (mykey, mystuff) values ('X', 123); exception when dup_val_on_index then update t set mystuff = 123 where mykey = 'X'; end;

예외 검사를 사용하지 않는 다른 대안:

UPDATE tablename SET val1 = in_val1, val2 = in_val2 WHERE val3 = in_val3; IF ( sql%rowcount = 0 ) THEN INSERT INTO tablename VALUES (in_val1, in_val2, in_val3); END IF; 없는 경우 삽입 업데이트: 마이테이블에 삽입(id1, t1)듀얼에서 11, 'x1' 선택존재하지 않는 곳(mytble에서 id1 WHERE 1 = 11); 업데이트 mytable SET t1 = 'x1' WHERE ID1 = 11;

팀 실베스터의 코멘트에서 지적된 바와 같이 동시 접속이 가능한 상황에서 지금까지 나온 답변 중 어느 것도 안전하지 않으며, 레이스의 경우 예외를 제기할 것이다.이 문제를 해결하려면 insert/update 콤보를 일종의 루프 스테이트먼트로 감싸야 합니다.그러면 예외 발생 시 모든 것을 재시도할 수 있습니다.

예를 들어, Grommit의 코드를 루프로 감싸 동시에 실행할 때 안전하게 할 수 있는 방법은 다음과 같습니다.

PROCEDURE MyProc ( ... ) IS BEGIN LOOP BEGIN MERGE INTO Employee USING dual ON ( "id"=2097153 ) WHEN MATCHED THEN UPDATE SET "last"="smith" , "name"="john" WHEN NOT MATCHED THEN INSERT ("id","last","name") VALUES ( 2097153,"smith", "john" ); EXIT; -- success? -> exit loop EXCEPTION WHEN NO_DATA_FOUND THEN -- the entry was concurrently deleted NULL; -- exception? -> no op, i.e. continue looping WHEN DUP_VAL_ON_INDEX THEN -- an entry was concurrently inserted NULL; -- exception? -> no op, i.e. continue looping END; END LOOP; END;

트랜잭션 모드인 N.B.SERIALIZABLEORA-08177: 이 트랜잭션 예외에 대한 액세스를 직렬화할 수 없습니다.

그로밋이 대답하고 싶은데, 다만 중복된 값이 필요해요.한 번 표시되는 솔루션을 찾았습니다.http://forums.devshed.com/showpost.php?p=1182653&postcount=2

MERGE INTO KBS.NUFUS_MUHTARLIK B USING ( SELECT '028-01' CILT, '25' SAYFA, '6' KUTUK, '46603404838' MERNIS_NO FROM DUAL ) E ON (B.MERNIS_NO = E.MERNIS_NO) WHEN MATCHED THEN UPDATE SET B.CILT = E.CILT, B.SAYFA = E.SAYFA, B.KUTUK = E.KUTUK WHEN NOT MATCHED THEN INSERT ( CILT, SAYFA, KUTUK, MERNIS_NO) VALUES (E.CILT, E.SAYFA, E.KUTUK, E.MERNIS_NO);

난 몇 년 동안 첫 번째 코드 샘플을 사용해왔어.카운트가 아니라 not found(찾을 수 없음)입니다.

UPDATE tablename SET val1 = in_val1, val2 = in_val2 WHERE val3 = in_val3; IF ( sql%notfound ) THEN INSERT INTO tablename VALUES (in_val1, in_val2, in_val3); END IF;

아래 코드는 새로운 개선 코드일 수 있습니다.

MERGE INTO tablename USING dual ON ( val3 = in_val3 ) WHEN MATCHED THEN UPDATE SET val1 = in_val1, val2 = in_val2 WHEN NOT MATCHED THEN INSERT VALUES (in_val1, in_val2, in_val3)

첫 번째 예에서는 업데이트가 인덱스를 검색합니다.오른쪽 행을 업데이트하려면 이 작업을 수행해야 합니다.Oracle은 암묵적인 커서를 열고 해당 삽입을 래핑하기 위해 이 커서를 사용합니다.그러면 삽입은 키가 존재하지 않는 경우에만 이루어집니다.그러나 insert는 독립된 명령어이므로 두 번째 검색을 수행해야 합니다.merge 명령어의 내부 동작은 알 수 없지만 명령어가 단일 단위이기 때문에 Oracle은 단일 인덱스 룩업으로 올바른 삽입 또는 업데이트를 실행할 수 있습니다.

일부 테이블에서 데이터를 가져와 테이블을 업데이트하거나 행을 삽입하거나 삭제하는 등의 처리가 필요한 경우에는 병합이 더 낫다고 생각합니다.단, 단일 행의 경우 구문이 더 일반적이기 때문에 첫 번째 경우를 고려할 수 있습니다.

다음 두 가지 솔루션에 대한 참고 사항:

1) 예외인 경우 삽입 후 갱신한다.

또는

2) sql%rowcount = 0인 경우 업데이트한 후

먼저 삽입할지 업데이트할지 여부도 애플리케이션에 따라 달라집니다.추가 삽입 또는 추가 업데이트가 필요합니까?성공할 가능성이 가장 높은 사람이 먼저 가야 한다.

잘못된 항목을 선택하면 불필요한 색인 읽기가 많이 발생합니다.큰 문제는 아니지만 고려해야 할 사항입니다.

이거 드셔보세요.

insert into b_building_property ( select 'AREA_IN_COMMON_USE_DOUBLE','Area in Common Use','DOUBLE', null, 9000, 9 from dual ) minus ( select * from b_building_property where id = 9 ) ;

http://www.praetoriate.com/oracle_tips_upserts.htm 에서 :

"Oracle9i에서는 UPSERT가 하나의 스테이트먼트로 이 작업을 수행할 수 있습니다."

INSERT FIRST WHEN credit_limit >=100000 THEN INTO rich_customers VALUES(cust_id,cust_credit_limit) INTO customers ELSE INTO customers SELECT * FROM new_customers;

언급URL : https://stackoverflow.com/questions/237327/oracle-how-to-upsert-update-or-insert-into-a-table



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3